from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger
from app.db.session import get_db
from app.db.models import AlertRule, AlertHistory, AlertTaskGroup
from app.core.checker import RuleChecker
from app.core.notifier import Notifier
from app.core.frequency_checker import FrequencyChecker
import logging
from datetime import datetime
from config import Config
import pytz

logger = logging.getLogger(__name__)

scheduler = None


def check_task_group_rules(group_name):
    """检查特定任务组的所有规则"""
    logger.info(f"开始检查任务组 '{group_name}' 的规则")
    start_time = datetime.now()

    # 使用Bcenter数据库
    Bcenter = next(get_db())
    try:
        db_dict={}
        # 获取该任务组所有启用的规则
        rules = Bcenter.query(AlertRule).filter(
            AlertRule.task_group == group_name,
            AlertRule.is_active == True
        ).all()

        if not rules:
            logger.info(f"任务组 '{group_name}' 没有启用的规则")
            return

        notifier = Notifier()
        triggered_count = 0
        db_dict = {'Bcenter': Bcenter}

        for rule in rules:
            try:
                # 检查频率是否满足
                freq_checker = FrequencyChecker(rule)
                if not freq_checker.should_trigger():
                    logger.debug(f"规则 {rule.rule_name} 未到触发时间，跳过")
                    continue

                logger.info(f"检查规则: {rule.rule_name}")

                # 获取源数据库
                if rule.origin_db not in db_dict:
                    db_dict[rule.origin_db] = next(get_db(DB_KEY=rule.origin_db))
                origin_db = db_dict[rule.origin_db]

                # 获取目标数据库
                if rule.dest_db not in db_dict:
                    db_dict[rule.dest_db] = next(get_db(DB_KEY=rule.dest_db))
                dest_db = db_dict[rule.dest_db]

                # 创建检查器
                checker = RuleChecker(Bcenter, origin_db, dest_db)

                # 检查规则
                triggered, actual_value, standard_value, operator,base_dict = checker.check_rule(rule)

                if triggered:
                    logger.warning(f"规则触发: {rule.rule_name}, 当前值: {actual_value}")
                    triggered_count += 1

                    # 发送通知
                    success, method = notifier.notify(rule, actual_value,standard_value,base_dict)

                    # 记录历史
                    history = AlertHistory(
                        rule_id=rule.id,
                        rule_name=rule.rule_name,
                        standard_value=str(standard_value),
                        operator=operator,
                        actual_value=str(actual_value),
                        trigger_time=datetime.now(pytz.timezone(rule.timezone or 'Asia/Shanghai')),
                        notification_flag=triggered,
                        notification_sent=success,
                        notification_method=method
                    )
                    Bcenter.add(history)

                    # 更新最后触发时间
                    rule.last_trigger_time = datetime.now(pytz.timezone(rule.timezone or 'Asia/Shanghai'))
                    Bcenter.commit()
                    logger.info(f"已记录规则 {rule.rule_name} 的触发历史")
                else:
                    # 记录历史
                    history = AlertHistory(
                        rule_id=rule.id,
                        rule_name=rule.rule_name,
                        actual_value=str(actual_value),
                        operator=operator,
                        standard_value=str(standard_value),
                        trigger_time=datetime.now(pytz.timezone(rule.timezone or 'Asia/Shanghai')),
                        notification_flag=triggered,
                        notification_sent=False,
                        notification_method=""
                    )
                    Bcenter.add(history)
                    # 更新最后触发时间
                    rule.last_trigger_time = datetime.now(pytz.timezone(rule.timezone or 'Asia/Shanghai'))
                    Bcenter.commit()

            except Exception as e:
                logger.error(f"检查规则 {rule.rule_name} 时出错: {e}")
                Bcenter.rollback()

        elapsed = (datetime.now() - start_time).total_seconds()
        logger.info(
            f"任务组 '{group_name}' 检查完成: 共检查 {len(rules)} 条规则, 触发 {triggered_count} 条, 耗时 {elapsed:.2f} 秒")

    except Exception as e:
        logger.error(f"检查任务组 '{group_name}' 失败: {e}")
    finally:
        # 关闭所有数据库连接
        for key, session in db_dict.items():
            if key != 'Bcenter':  # Bcenter会在外层关闭
                try:
                    session.close()
                except:
                    pass
        Bcenter.close()


class AlertTaskManager:
    def __init__(self):
        self.scheduler = BackgroundScheduler()
        self.scheduler.configure(timezone=pytz.timezone(Config.DEFAULT_TIMEZONE))
        self.task_jobs = {}  # 存储任务ID到APScheduler作业的映射

    def initialize(self):
        """初始化任务管理器，加载所有启用的任务组"""
        logger.info("初始化预警任务管理器")
        Bcenter = next(get_db())
        try:
            task_groups = Bcenter.query(AlertTaskGroup).filter(AlertTaskGroup.is_active == True).all()
            for task_group in task_groups:
                self.add_task_group(task_group)

            self.scheduler.start()
            logger.info(f"已启动定时任务调度器，共加载 {len(task_groups)} 个任务组")
        except Exception as e:
            logger.error(f"初始化任务管理器失败: {e}")
        finally:
            Bcenter.close()

    def add_task_group(self, task_group):
        """添加任务组到调度器"""
        try:
            if task_group.schedule_type == 'interval':
                trigger = IntervalTrigger(**task_group.schedule_value)
            elif task_group.schedule_type == 'cron':
                trigger = CronTrigger(**task_group.schedule_value)
            else:
                logger.error(f"未知的调度类型: {task_group.schedule_type}")
                return

            job = self.scheduler.add_job(
                check_task_group_rules,
                trigger=trigger,
                args=[task_group.group_name],
                id=f"task_group_{task_group.id}",
                name=f"任务组: {task_group.group_name}",
                max_instances=1,
                misfire_grace_time=300  # 5分钟容差
            )

            self.task_jobs[task_group.id] = job
            logger.info(f"已添加任务组: {task_group.group_name} ({task_group.schedule_type})")
        except Exception as e:
            logger.error(f"添加任务组 {task_group.group_name} 失败: {e}")

    def shutdown(self):
        """关闭调度器"""
        if self.scheduler.running:
            self.scheduler.shutdown()
            logger.info("任务调度器已关闭")


# 全局任务管理器实例
task_manager = AlertTaskManager()


def start_scheduler():
    global scheduler
    if scheduler and scheduler.running:
        return
    # 初始化任务管理器
    task_manager.initialize()
    scheduler = task_manager.scheduler

def shutdown_scheduler():
    global scheduler
    if scheduler:
        task_manager.shutdown()
        scheduler = None
        logger.info("定时任务已关闭")